#!/usr/bin/python3
import datetime
import queue
import threading
import time
from multiprocessing import cpu_count
from typing import Dict

import requests

import dto
from action import QuantifyBase

# 量化算法名称+函数表
action_kv: Dict[str, QuantifyBase] = {}
base_act: QuantifyBase = QuantifyBase()
# 添加新的类型
action_kv['BASE'] = base_act


def GetCurDay() -> str:
    return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")


def CopyRsp(req: dto.QuantifyRequest, rsp: dto.CBResponse) -> dto.CBResponse:
    """"""
    cb = dto.CBResponse(symbol=rsp.symbol, name=req.name, method=req.method,
                        status=rsp.status, msg=rsp.msg,
                        tid=rsp.tid, action=rsp.action,
                        day=GetCurDay())
    return cb


class ActFacade:
    def pop(self) -> dto.QuantifyRequest:
        return None


class ActPlay(threading.Thread):
    """"""

    def __init__(self, tid: int, name: str, act: ActFacade):
        threading.Thread.__init__(self)
        self.tid = tid
        self.name = name
        self.act = act
        self.stop = False

    def doStop(self):
        self.stop = True

    def doWork(self) -> int:
        try:
            req = self.act.pop()
            if req is None:
                return -1
            """"""
            actor = action_kv.get(req.method)
            rsp = actor.act(req)
            # 回调回去
            cb = CopyRsp(req, rsp)
            r = requests.post(req.cbUrl, json=cb.model_dump())
            if r.status_code != 200:
                """"""
                print("cbUrl:", req.cbUrl, "code:", r.status_code, ",msg:", r.text)
            else:
                """"""
                print("code:", r.status_code)
            return 0
        except Exception as ex:
            """"""
            print("ex:", ex)
            return -1

    def run(self) -> None:
        """"""
        print("tid:", self.tid, ",name:", self.name, " started...")
        while not self.stop:
            """"""
            if self.doWork() == 0:
                """"""
                time.sleep(1)
            else:
                time.sleep(5)
        print("tid:", self.tid, ",name:", self.name, " over")


class QuantActor(ActFacade):
    """"""

    def __init__(self):
        """"""
        self.q = queue.Queue(100)
        self.actors: list[ActPlay] = []

    def start(self):
        cpus = cpu_count()
        num = int((cpus * 2) / 3)
        if num == 0:
            """"""
            num = 1
        print("cpu_count:", cpus, ",thread num:", num)
        for n in range(0, num):
            """"""
            thd = ActPlay(n, ("thread-%d" % n), self)
            thd.start()
            self.actors.append(thd)
        return

    def notifyStop(self):
        for t in self.actors:
            """"""
            t.doStop()

    def put(self, req: dto.QuantifyRequest):
        """"""
        self.q.put(req, True)

    def pop(self) -> dto.QuantifyRequest:
        try:
            item = self.q.get(True, 3)
            if item is None:
                return None
            return item
        except Exception as ex:
            return None


glb_actor: QuantActor = QuantActor()


def startActor() -> QuantActor:
    glb_actor.start()
    return glb_actor


def stopActor():
    glb_actor.notifyStop()


# 同步调用接口
def syncActor(req: dto.QuantifyRequest) -> dto.CBResponse:
    act = action_kv.get(req.method)
    if act is None:
        """"""
        return base_act.act(req)
    else:
        return act.act(req)


def asyncActor(req: dto.QuantifyRequest) -> dto.Response:
    act = action_kv.get(req.method)
    rsp = dto.Response(tid=req.tid, symbol=req.symbol)
    if act is None:
        rsp.status = 404
        rsp.msg = "Not found"
    else:
        """"""
        glb_actor.put(req)
        rsp.status = 200
        rsp.msg = "OK"
    return rsp
